#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <cstring>
//客户端链接时需要提前知道ip和端口号
int main(int argc,char*argv[])
{
    if(argc!=3)
    {
        std::cerr<<"Usage :"<<argv[0]/*可执行程序对应的名称*/<<"server ip,server port"<<std::endl;
        exit(0);
    }

    std::string serverip=argv[1];
    uint16_t  serverport=std::stoi(argv[2]);
     int socket=::socket(AF_INET,SOCK_DGRAM,0);
     if(socket<0)
    {
        std::cerr<<"socket create fail"<<std::endl;
        exit(1);
    }
    //client需要bind端口,但是不需要显示bind自己的Ip和端口
    //客户端在首次发送数据时，客户端的os会自动Bind客户端的ip和端口号
    //client的端口号由os随机选择（为了规避重复端口），不给用户自己设定
    //客户端发送数据前需要知道ip 和端口号
    
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=htons(serverport);//序列转换
    server.sin_addr.s_addr=inet_addr(serverip.c_str());//字符串风格的ip转换

    while(1)
    {
        std::string line;
        std::cout<<"Please Enter#";
        std::getline(std::cin,line);
        std::cout<<"line message is@"<<line<<std::endl;
        //发消息，自动绑定端口IP
        int n=sendto(socket,line.c_str(),line.size(),0,(struct sockaddr*)&server,sizeof(server));//发消息得明确发送对象
        if(n>0)
        {
             struct sockaddr_in temp;
            socklen_t len=sizeof(temp);

            char buffer[1024];
            int m=recvfrom(socket,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);//udp客户端不面向链接
            if(m>0)
            {
                buffer[m]=0;
                std::cout<<buffer<<std::endl;
            }
            else
            {
            std::cout<<"recvfrom erro"<<std::endl;
                break;
            }
        }
        else
        {
            std::cout<<"sendto erro"<<std::endl;
            break;
        }
    }


    ::close(socket);

    return 0;
}